#include <tinyhal.h>
#include <Drivers\BlockStorage\WearLeveling\BS_WearLeveling.h>
#include <Targets\Native\FM4\DeviceCode\FM4_Blockstorage\NandFlash\NandFlash_BL.h>

//--//

#define FLASH_MANUFACTURER_CODE                 0x98
#define FLASH_DEVICE_CODE                       0xD3
#define FLASH_BASE_ADDRESS                      0x60000000
#define FLASH_SIZE                              0x01000000
#define FLASH_BLOCK_COUNT                       2048
#define FLASH_SECTOR_PER_BLOCK                  64
#define FLASH_SECTOR_SIZE                       4096
#define FLASH_BLOCK_SIZE                        (FLASH_SECTOR_PER_BLOCK*FLASH_SECTOR_SIZE)
#define FLASH_BLOCK_ERASE_TYPICAL_TIME_USEC     1500000
#define FLASH_SECTOR_WRITE_TYPICAL_TIME_USEC    200
#define FLASH_BLOCK_ERASE_MAX_TIME_USEC         2000000
#define FLASH_SECTOR_WRITE_MAX_TIME_USEC        700

#define TC58NVG3S0F_SIZE_IN_BYTES                  (FLASH_BLOCK_SIZE*FLASH_BLOCK_COUNT)
#define TC58NVG3S0F_WP_GPIO_PIN                    GPIO_PIN_NONE
#define TC58NVG3S0F_WP_ACTIVE                      FALSE

// BlockDeviceInformation

#define TC58NVG3S0F_IS_REMOVABLE                   FALSE
#define TC58NVG3S0F_SUPPORTS_XIP                   FALSE
#define TC58NVG3S0F_WRITE_PROTECTED                FALSE
#define TC58NVG3S0F_NUM_REGIONS                    1

//--//
#ifdef MEMORY_USAGE_SPECIAL
#undef MEMORY_USAGE_SPECIAL
#endif

#ifdef MEMORY_USAGE_SPECIAL2
#undef MEMORY_USAGE_SPECIAL2
#endif

#ifdef MEMORY_USAGE_SPECIAL3
#undef MEMORY_USAGE_SPECIAL3
#endif

#if defined(MEMORY_USAGE_GCC_SPECIAL_CODE)
#undef MEMORY_USAGE_GCC_SPECIAL_CODE
#endif

//--//
const BlockRange g_TC58NVG3S0F_BlockStatus[] =
{
    // { BlockRange::BLOCKTYPE_FILESYSTEM, 0, FLASH_BLOCK_COUNT - 1 }
    { BlockRange::BLOCKTYPE_FILESYSTEM, 10, 29 }
};

const BlockRegionInfo  g_TC58NVG3S0F_BlkRegion[TC58NVG3S0F_NUM_REGIONS] =
{
    FLASH_BASE_ADDRESS,             // ByteAddress  Start;              // Starting Sector address
    FLASH_BLOCK_COUNT,              // UINT32       NumBlocks;          // total number of blocks in this region
    FLASH_BLOCK_SIZE,               // UINT32       BytesPerBlock;      // Total number of bytes per block (MUST be SectorsPerBlock * DataBytesPerSector)

    ARRAYSIZE_CONST_EXPR(g_TC58NVG3S0F_BlockStatus),
    g_TC58NVG3S0F_BlockStatus,
};

//--//

#undef MEMORY_USAGE_GCC_SPECIAL_CODE

//--//

const BlockDeviceInfo  g_TC58NVG3S0F_DeviceInfo=
{
    {
        TC58NVG3S0F_IS_REMOVABLE,
        TC58NVG3S0F_SUPPORTS_XIP,
        TC58NVG3S0F_WRITE_PROTECTED,
    },
    FLASH_SECTOR_WRITE_MAX_TIME_USEC,           // UINT32 Duration_Max_WordWrite_uSec;
    FLASH_BLOCK_ERASE_MAX_TIME_USEC,            // UINT32 Duration_Max_SectorErase_uSec;
    FLASH_SECTOR_SIZE,                          // UINT32 BytesPerSector;

    FLASH_SIZE,                                 // UINT32 Size;

    ARRAYSIZE_CONST_EXPR(g_TC58NVG3S0F_BlkRegion),  // UINT32 NumRegions;
    g_TC58NVG3S0F_BlkRegion,                        // const BlockRegionInfo* pRegions;
};


struct BLOCK_CONFIG g_TC58NVG3S0F_BS_Config =
{
    {
        TC58NVG3S0F_WP_GPIO_PIN,               // GPIO_PIN             Pin;
        TC58NVG3S0F_WP_ACTIVE,                 // BOOL                 ActiveState;
    },

    &g_TC58NVG3S0F_DeviceInfo,             // BlockDeviceinfo
};

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rwdata = "g_TC58NVG3S0F_BS_WL"
#endif

extern struct IBlockStorageDevice g_NandFlash_BL_DeviceTable;

struct BS_WearLeveling_Config g_TC58NVG3S0F_WearLeveling_Config =
{
    &g_TC58NVG3S0F_BS_Config,

    &g_NandFlash_BL_DeviceTable,

    0,
    FLASH_BLOCK_SIZE,
    FLASH_BASE_ADDRESS,

    NULL,
};

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rwdata
#endif

//--//

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rodata = "g_TC58NVG3S0F_BS"
#endif

struct BlockStorageDevice g_TC58NVG3S0F_BS;

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rodata
#endif

//--//

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rodata = "g_TC58NVG3S0F_BS_Driver"
#endif

struct NF_BS_Driver g_TC58NVG3S0F_BS_Driver;

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rodata 
#endif 

//--//

